home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / xform.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-04  |  16.1 KB  |  512 lines

  1. /* $Id: xform.c,v 3.3 1998/08/20 04:15:48 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: xform.c,v $
  26.  * Revision 3.3  1998/08/20 04:15:48  brianp
  27.  * added prototype 3.1 transformation functions
  28.  *
  29.  * Revision 3.2  1998/04/18 05:00:56  brianp
  30.  * renamed USE_ASM to USE_X86_ASM
  31.  *
  32.  * Revision 3.1  1998/02/01 16:37:19  brianp
  33.  * added GL_EXT_rescale_normal extension
  34.  *
  35.  * Revision 3.0  1998/01/31 21:08:31  brianp
  36.  * initial rev
  37.  *
  38.  */
  39.  
  40.  
  41. /*
  42.  * Matrix/vertex/vector transformation stuff
  43.  *
  44.  *
  45.  * NOTES:
  46.  * 1. 4x4 transformation matrices are stored in memory in column major order.
  47.  * 2. Points/vertices are to be thought of as column vectors.
  48.  * 3. Transformation of a point p by a matrix M is: p' = M * p
  49.  *
  50.  */
  51.  
  52.  
  53. #ifdef PC_HEADER
  54. #include "all.h"
  55. #else
  56. #include <math.h>
  57. #include "context.h"
  58. #include "mmath.h"
  59. #include "types.h"
  60. #include "xform.h"
  61. #endif
  62.  
  63.  
  64.  
  65. /*
  66.  * Apply a transformation matrix to an array of [X Y Z W] coordinates:
  67.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  68.  * where p[i] and q[i] are 4-element column vectors and m is a 16-element
  69.  * transformation matrix.
  70.  */
  71. void gl_xform_points_4fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  72.               GLfloat p[][4] )
  73. {
  74.    /* This function has been carefully crafted to maximize register usage
  75.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  76.     * will like this code too.
  77.     */
  78.    {
  79.       GLuint i;
  80.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  81.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  82.       if (m12==0.0F && m13==0.0F) {
  83.      /* common case */
  84.      for (i=0;i<n;i++) {
  85.         GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  86.         q[i][0] = m0 * p0 + m4  * p1 + m8 * p2;
  87.         q[i][1] = m1 * p0 + m5  * p1 + m9 * p2;
  88.      }
  89.       }
  90.       else {
  91.      /* general case */
  92.      for (i=0;i<n;i++) {
  93.         GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  94.         q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12 * p3;
  95.         q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13 * p3;
  96.      }
  97.       }
  98.    }
  99.    {
  100.       GLuint i;
  101.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  102.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  103.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  104.      /* common case */
  105.      for (i=0;i<n;i++) {
  106.         GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  107.         q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  108.         q[i][3] = p3;
  109.      }
  110.       }
  111.       else {
  112.      /* general case */
  113.      for (i=0;i<n;i++) {
  114.         GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  115.         q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  116.         q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15 * p3;
  117.      }
  118.       }
  119.    }
  120. }
  121.  
  122.  
  123.  
  124. /*
  125.  * Apply a transformation matrix to an array of [X Y Z] coordinates:
  126.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  127.  */
  128. void gl_xform_points_3fv( GLuint n, GLfloat q[][4], const GLfloat m[16],
  129.               GLfloat p[][3] )
  130. {
  131.    /* This function has been carefully crafted to maximize register usage
  132.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  133.     * will like this code too.
  134.     */
  135.    {
  136.       GLuint i;
  137.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  138.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  139.       for (i=0;i<n;i++) {
  140.      GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  141.      q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12;
  142.      q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13;
  143.       }
  144.    }
  145.    {
  146.       GLuint i;
  147.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  148.       GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  149.       if (m3==0.0F && m7==0.0F && m11==0.0F && m15==1.0F) {
  150.      /* common case */
  151.      for (i=0;i<n;i++) {
  152.         GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  153.         q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  154.         q[i][3] = 1.0F;
  155.      }
  156.       }
  157.       else {
  158.      /* general case */
  159.      for (i=0;i<n;i++) {
  160.         GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2];
  161.         q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14;
  162.         q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15;
  163.      }
  164.       }
  165.    }
  166. }
  167.  
  168.  
  169. #if !defined(AMIGA)
  170. #ifndef USE_X86_ASM
  171. /*
  172.  * Apply a transformation matrix to an array of normal vectors:
  173.  *   for i in 0 to n-1 do  v[i] = u[i] * m
  174.  * where u[i] and v[i] are 3-element row vectors and m is a 16-element
  175.  * transformation matrix.
  176.  * If the normalize flag is true the normals will be scaled to length 1.
  177.  * If the rescale flag is true then do normal rescaling.
  178.  */
  179. void gl_xform_normals_3fv( GLuint n, GLfloat v[][3], const GLfloat m[16],
  180.                GLfloat u[][3], GLboolean normalize,
  181.                GLboolean rescale )
  182. {
  183.    if (normalize) {
  184.       if (rescale) {
  185.      /* Transform normals, rescale and normalize */
  186.      GLuint i;
  187.      GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  188.      GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  189.      GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  190.      GLfloat f = GL_SQRT( m2*m2 + m6*m6 + m10*m10 );
  191.      f = (f == 0.0F) ? 1.0F : (1.0F / f);
  192.      for (i=0;i<n;i++) {
  193.         GLdouble tx, ty, tz;
  194.         {
  195.            GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  196.            tx = f * (ux * m0 + uy * m1 + uz * m2);
  197.            ty = f * (ux * m4 + uy * m5 + uz * m6);
  198.            tz = f * (ux * m8 + uy * m9 + uz * m10);
  199.         }
  200.         {
  201.            GLdouble len, scale;
  202.            len = GL_SQRT( tx*tx + ty*ty + tz*tz );
  203.            scale = (len>1E-30) ? (1.0 / len) : 1.0;
  204.            v[i][0] = tx * scale;
  205.            v[i][1] = ty * scale;
  206.            v[i][2] = tz * scale;
  207.         }
  208.      }
  209.       }
  210.       else {
  211.      /* Transform and normalize */
  212.      GLuint i;
  213.      GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  214.      GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  215.      GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  216.      for (i=0;i<n;i++) {
  217.         GLdouble tx, ty, tz;
  218.         {
  219.            GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  220.            tx = ux * m0 + uy * m1 + uz * m2;
  221.            ty = ux * m4 + uy * m5 + uz * m6;
  222.            tz = ux * m8 + uy * m9 + uz * m10;
  223.         }
  224.         {
  225.            GLdouble len, scale;
  226.            len = GL_SQRT( tx*tx + ty*ty + tz*tz );
  227.            scale = (len>1E-30) ? (1.0 / len) : 1.0;
  228.            v[i][0] = tx * scale;
  229.            v[i][1] = ty * scale;
  230.            v[i][2] = tz * scale;
  231.         }
  232.      }
  233.       }
  234.    }
  235.    else {
  236.       if (rescale) {
  237.      /* Transform and rescale */
  238.      GLuint i;
  239.      GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  240.      GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  241.      GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  242.      GLfloat f = GL_SQRT( m2*m2 + m6*m6 + m10*m10 );
  243.      f = (f == 0.0F) ? 1.0F : (1.0F / f);
  244.      for (i=0;i<n;i++) {
  245.         GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  246.         v[i][0] = f * (ux * m0 + uy * m1 + uz * m2);
  247.         v[i][1] = f * (ux * m4 + uy * m5 + uz * m6);
  248.         v[i][2] = f * (ux * m8 + uy * m9 + uz * m10);
  249.      }
  250.       }
  251.       else {
  252.      /* Just transform */
  253.      GLuint i;
  254.      GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  255.      GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  256.      GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  257.      for (i=0;i<n;i++) {
  258.         GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  259.         v[i][0] = ux * m0 + uy * m1 + uz * m2;
  260.         v[i][1] = ux * m4 + uy * m5 + uz * m6;
  261.         v[i][2] = ux * m8 + uy * m9 + uz * m10;
  262.      }
  263.       }
  264.    }
  265. }
  266. #endif
  267. #endif
  268.  
  269. /*
  270.  * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix.  This
  271.  * function is used for transforming clipping plane equations and spotlight
  272.  * directions.
  273.  * Mathematically,  u = v * m.
  274.  * Input:  v - input vector
  275.  *         m - transformation matrix
  276.  * Output:  u - transformed vector
  277.  */
  278. void gl_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
  279. {
  280.    GLfloat v0=v[0], v1=v[1], v2=v[2], v3=v[3];
  281. #define M(row,col)  m[col*4+row]
  282.    u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
  283.    u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
  284.    u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
  285.    u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
  286. #undef M
  287. }
  288.  
  289.  
  290.  
  291. /**********************************************************************
  292.  *
  293.  * Mesa 3.1 prototype transformation code
  294.  *
  295.  * Objectives:
  296.  *     Move all functions which may be asm-accelerated out of vbxform.c
  297.  *       into this file.
  298.  *
  299.  *     Add support for arbitrary strides in source coordinates to better
  300.  *       support vertex arrays.
  301.  *
  302.  **********************************************************************/
  303.  
  304.  
  305.  
  306. /*
  307.  * Use the current modelview matrix to transform XYZ vertices from object
  308.  * to eye coordinates.
  309.  * Input:  ctx - the context
  310.  *         n - number of vertices to transform
  311.  *         stride - stride in bytes between subsequent vObj vertices
  312.  *         vObj - pointer to first vertex (in object coordinates)
  313.  * Output;  vEye - array [n][4] of eye coordinates
  314.  */
  315. void
  316. gl_transform_points3( const GLcontext *ctx, GLuint n, GLuint stride,
  317.               const GLfloat *vObj, GLfloat vEye[][4] )
  318. {
  319.    ASSERT((stride & 0x3) == 0);  /* multiple of 4 bytes */
  320.  
  321.    switch (ctx->ModelViewMatrixType) {
  322.       case MATRIX_GENERAL:
  323.      {
  324.         const GLfloat *m = ctx->ModelViewMatrix;
  325.         const GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  326.         const GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  327.         const GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  328.         const GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  329.         GLuint i;
  330.         for (i=0;i<n;i++) {
  331.            const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  332.            vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12;
  333.            vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13;
  334.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
  335.            vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
  336.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  337.         }
  338.      }
  339.      break;
  340.       case MATRIX_IDENTITY:
  341.      {
  342.         GLuint i;
  343.         for (i=0;i<n;i++) {
  344.            vEye[i][0] = vObj[0];
  345.            vEye[i][1] = vObj[1];
  346.            vEye[i][2] = vObj[2];
  347.            vEye[i][3] = 1.0F;
  348.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  349.         }
  350.      }
  351.      break;
  352.       case MATRIX_2D:
  353.      {
  354.         const GLfloat *m = ctx->ModelViewMatrix;
  355.         const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  356.         const GLfloat m12 = m[12], m13 = m[13];
  357.         GLuint i;
  358.         for (i=0;i<n;i++) {
  359.            const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  360.            vEye[i][0] = m0 * ox + m4 * oy            + m12       ;
  361.            vEye[i][1] = m1 * ox + m5 * oy            + m13       ;
  362.            vEye[i][2] =                   +       oz             ;
  363.            vEye[i][3] =                                      1.0F;
  364.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  365.         }
  366.      }
  367.      break;
  368.       case MATRIX_2D_NO_ROT:
  369.      {
  370.         const GLfloat *m = ctx->ModelViewMatrix;
  371.         const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  372.         GLuint i;
  373.         for (i=0;i<n;i++) {
  374.            const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  375.            vEye[i][0] = m0 * ox                      + m12       ;
  376.            vEye[i][1] =           m5 * oy            + m13       ;
  377.            vEye[i][2] =                   +       oz             ;
  378.            vEye[i][3] =                                      1.0F;
  379.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  380.         }
  381.      }
  382.      break;
  383.       case MATRIX_3D:
  384.      {
  385.         const GLfloat *m = ctx->ModelViewMatrix;
  386.         const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4];
  387.         const GLfloat m5 = m[5], m6 = m[6], m8 = m[8], m9 = m[9];
  388.         const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
  389.         GLuint i;
  390.         for (i=0;i<n;i++) {
  391.            const GLfloat ox = vObj[0], oy = vObj[1], oz = vObj[2];
  392.            vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12       ;
  393.            vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13       ;
  394.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14       ;
  395.            vEye[i][3] =                                      1.0F;
  396.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  397.         }
  398.      }
  399.      break;
  400.       default:
  401.      /* should never get here */
  402.      gl_problem( NULL, "invalid matrix type in gl_transform_points3()" );
  403.    }
  404. }
  405.  
  406.  
  407. /*
  408.  * Use the current modelview matrix to transform XYZW vertices from object
  409.  * to eye coordinates.
  410.  * Input:  ctx - the context
  411.  *         n - number of vertices to transform
  412.  *         stride - stride in bytes between subsequent vObj vertices
  413.  *         vObj - pointer to first vertex (in object coordinates)
  414.  * Output;  vEye - array [n][4] of eye coordinates
  415.  */
  416. void
  417. gl_transform_points4( const GLcontext *ctx, GLuint n, GLuint stride,
  418.               const GLfloat *vObj, GLfloat vEye[][4] )
  419. {
  420.    ASSERT((stride & 0x3) == 0);  /* multiple of 4 bytes */
  421.  
  422.    switch (ctx->ModelViewMatrixType) {
  423.       case MATRIX_GENERAL:
  424.      {
  425.         const GLfloat *m = ctx->ModelViewMatrix;
  426.         const GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8],  m12 = m[12];
  427.         const GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9],  m13 = m[13];
  428.         const GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10],  m14 = m[14];
  429.         const GLfloat m3 = m[3],  m7 = m[7],  m11 = m[11],  m15 = m[15];
  430.         GLuint i;
  431.         for (i=0;i<n;i++) {
  432.            const GLfloat ox = vObj[0], oy = vObj[1];
  433.            const GLfloat oz = vObj[2], ow = vObj[3];
  434.            vEye[i][0] = m0 * ox + m4 * oy + m8  * oz + m12 * ow;
  435.            vEye[i][1] = m1 * ox + m5 * oy + m9  * oz + m13 * ow;
  436.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  437.            vEye[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
  438.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  439.         }
  440.      }
  441.      break;
  442.       case MATRIX_IDENTITY:
  443.      {
  444.         GLuint i;
  445.         for (i=0;i<n;i++) {
  446.            vEye[i][0] = vObj[0];
  447.            vEye[i][1] = vObj[1];
  448.            vEye[i][2] = vObj[2];
  449.            vEye[i][3] = vObj[3];
  450.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  451.         }
  452.      }
  453.      break;
  454.       case MATRIX_2D:
  455.      {
  456.         const GLfloat *m = ctx->ModelViewMatrix;
  457.         const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
  458.         const GLfloat m12 = m[12], m13 = m[13];
  459.         GLuint i;
  460.         for (i=0;i<n;i++) {
  461.            const GLfloat ox = vObj[0], oy = vObj[1];
  462.            const GLfloat oz = vObj[2], ow = vObj[3];
  463.            vEye[i][0] = m0 * ox + m4 * oy            + m12 * ow;
  464.            vEye[i][1] = m1 * ox + m5 * oy            + m13 * ow;
  465.            vEye[i][2] =                   +       oz           ;
  466.            vEye[i][3] =                                      ow;
  467.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  468.         }
  469.      }
  470.      break;
  471.       case MATRIX_2D_NO_ROT:
  472.      {
  473.         const GLfloat *m = ctx->ModelViewMatrix;
  474.         const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
  475.         GLuint i;
  476.         for (i=0;i<n;i++) {
  477.            const GLfloat ox = vObj[0], oy = vObj[1];
  478.            const GLfloat oz = vObj[2], ow = vObj[3];
  479.            vEye[i][0] = m0 * ox                      + m12 * ow;
  480.            vEye[i][1] =           m5 * oy            + m13 * ow;
  481.            vEye[i][2] =                   +       oz           ;
  482.            vEye[i][3] =                                      ow;
  483.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  484.         }
  485.      }
  486.      break;
  487.       case MATRIX_3D:
  488.      {
  489.         const GLfloat *m = ctx->ModelViewMatrix;
  490.         const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4];
  491.         const GLfloat m5 = m[5], m6 = m[6], m8 = m[8], m9 = m[9];
  492.         const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
  493.         GLuint i;
  494.         for (i=0;i<n;i++) {
  495.            const GLfloat ox = vObj[0], oy = vObj[1];
  496.            const GLfloat oz = vObj[2], ow = vObj[3];
  497.            vEye[i][0] = m0 * ox + m4 * oy +  m8 * oz + m12 * ow;
  498.            vEye[i][1] = m1 * ox + m5 * oy +  m9 * oz + m13 * ow;
  499.            vEye[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
  500.            vEye[i][3] =                                      ow;
  501.            vObj = (const GLfloat *) ((GLubyte *) vObj + stride);
  502.         }
  503.      }
  504.      break;
  505.       default:
  506.      /* should never get here */
  507.      gl_problem( NULL, "invalid matrix type in gl_transform_points4()" );
  508.    }
  509. }
  510.  
  511.  
  512.